package com.zmn.uac.business.impl.oauth.login;

import com.alibaba.fastjson.JSON;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.consts.GlobalConsts;
import com.zmn.saas.dubbo.dto.app.AppDRO;
import com.zmn.uac.business.interfaces.oauth.login.ByteDanceLoginBService;
import com.zmn.uac.business.template.oauth.login.BaseLoginTemplateMode;
import com.zmn.uac.common.constant.AccessTypeConstant;
import com.zmn.uac.common.constant.ByteDanceConstant;
import com.zmn.uac.common.dio.oauth.login.TempCodeDIO;
import com.zmn.uac.common.dio.oauth.login.UserAuthLoginDIO;
import com.zmn.uac.common.entity.oauth.login.*;
import com.zmn.uac.common.entity.oauth.phone.UserPhoneInfo;
import com.zmn.uac.common.info.UserAuthPhoneInfo;
import com.zmn.uac.common.info.bytebeat.ByteBeatAuthPhoneInfo;
import com.zmn.uac.common.info.bytebeat.ByteBeatMinProgramSessionInfo;
import com.zmn.uac.common.info.bytebeat.ByteBeatPhoneInfo;
import com.zmn.uac.common.info.bytebeat.ByteBeatUserInfo;
import com.zmn.uac.util.DecryptUtil;
import com.zmn.uac.util.HttpClientsUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.Objects;

/**
 * 类描述：字节跳动、抖音授权登陆实现
 *
 * @author xujie
 * @since 2021/06/11 18:53
 */
@Slf4j
@Service
public class ByteDanceLoginBServiceImpl extends BaseLoginTemplateMode implements ByteDanceLoginBService {

    private static final String TAG = "字节跳动、抖音授权登陆实现";

    @Override
    public ResponseDTO<UserAuthLoginInfo> thirdPartyUserDataAcquisition(UserAuthLoginDIO dio,
                                                                        UserAuthPhoneInfo authPhoneInfo) {

        Integer channelId = dio.getChannelId();
        AppDRO app = Objects.equals(dio.getAccessType(), AccessTypeConstant.SHOP)
                ? getAppInfoByShopId(dio.getShopId()) : getAppByChannelId(channelId);
        if (app == null) {
            return ResponseDTO.fail("查询应用为null");
        }
        ByteBeatAuthPhoneInfo byteBeatAuthPhoneInfo = (ByteBeatAuthPhoneInfo) authPhoneInfo;
        ResponseDTO<ByteBeatMinProgramSessionInfo> byteBeatMinProgramSessionInfoResponse = getByteBeatMinProgramSessionInfo(app.getThirdAppId(), app.getThirdAppSecret(), byteBeatAuthPhoneInfo.getCode(), byteBeatAuthPhoneInfo.getAnonymousCode(), dio.getUuid());
        if (!byteBeatMinProgramSessionInfoResponse.isSuccess()) {
            return ResponseDTO.fail(byteBeatMinProgramSessionInfoResponse.getMessage());
        }
        ByteBeatUserInfo byteBeatUserInfo = new ByteBeatUserInfo();
        ByteBeatPhoneInfo beatPhoneInfo;
        ByteBeatMinProgramSessionInfo beatMinProgramSessionInfo = byteBeatMinProgramSessionInfoResponse.getData();
        if (StringUtil.isBlank(authPhoneInfo.getMobile())) {
            // encryptedData为空的时候，就不需要解密手机号，直接用code进行登录注册
            if (StringUtil.isBlank(byteBeatAuthPhoneInfo.getEncryptedData())) {
                beatPhoneInfo = new ByteBeatPhoneInfo();
            } else {
                ResponseDTO<ByteBeatPhoneInfo> byteBeatPhoneInfoResponse = DecryptUtil.decrypt(byteBeatAuthPhoneInfo.getIv(), byteBeatAuthPhoneInfo.getEncryptedData(), beatMinProgramSessionInfo.getSessionKey(), ByteBeatPhoneInfo.class);
                if (byteBeatPhoneInfoResponse.isSuccess()) {
                    beatPhoneInfo = byteBeatPhoneInfoResponse.getData();
                } else {
                    beatPhoneInfo = new ByteBeatPhoneInfo();
                }
            }
        } else {
            beatPhoneInfo = ByteBeatPhoneInfo.builder().purePhoneNumber(authPhoneInfo.getMobile()).build();
        }
        UserPhoneInfo userPhoneInfo = UserPhoneInfo.builder().mobile(beatPhoneInfo.getPurePhoneNumber()).build();
        Integer gender = (byteBeatUserInfo.getGender() != null && byteBeatUserInfo.getGender() == 0) ? byteBeatUserInfo.getGender() : 3;
        String openId = StringUtils.isNotBlank(beatMinProgramSessionInfo.getOpenId()) ? beatMinProgramSessionInfo.getOpenId() : beatMinProgramSessionInfo.getAnonymousOpenid();

        UserInfo info = setUserInfo(openId, beatMinProgramSessionInfo, byteBeatUserInfo, gender);
        PlatInfo platInfo = setPlatInfo(dio, app, channelId);
        ThirdAppInfo thirdAppInfo = setThirdAppInfo(app);
        UserOtherInfo userOtherInfo = setUserOtherInfo(beatMinProgramSessionInfo);
        UserAuthLoginInfo userAuthLoginInfo = setUserAuthLoginInfo(info, userOtherInfo, platInfo, thirdAppInfo, userPhoneInfo);

        return ResponseDTO.success(userAuthLoginInfo);
    }

    /**
     * 获取openid
     *
     * @param tempCodeDIO
     * @param app
     * @return
     */
    @Override
    public ResponseDTO<String> getThirdPartyOpenIdByCode(TempCodeDIO tempCodeDIO, AppDRO app) {
        ResponseDTO<ByteBeatMinProgramSessionInfo> byteBeatMinProgramSessionInfoResponse =
                getByteBeatMinProgramSessionInfo(app.getThirdAppId(), app.getThirdAppSecret(), tempCodeDIO.getCode(), "", null);
        if (!byteBeatMinProgramSessionInfoResponse.isSuccess()) {
            return ResponseDTO.fail(byteBeatMinProgramSessionInfoResponse.getMessage());
        }
        log.info("获取字节调用响应byteBeatMinProgramSessionInfoResponse:{}", byteBeatMinProgramSessionInfoResponse.getData());

        return ResponseDTO.success(byteBeatMinProgramSessionInfoResponse.getData().getOpenId());
    }

    private ResponseDTO<ByteBeatMinProgramSessionInfo> getByteBeatMinProgramSessionInfo(String appId, String secret, String code, String anonymousCode, String uuid) {

        log.info("{}获取用户小程序授权code信息,参数:appId:{},secret:{},code:{},anonymousCode:{}", TAG, appId, secret, code, anonymousCode);
        String requestCodeUrl = String.format(ByteDanceConstant.CODE_2_SESSION_URL, appId, secret, code, anonymousCode);
        String jsonResult;
        try {
            jsonResult = HttpClientsUtil.executeGet(requestCodeUrl);
        } catch (Exception e) {
            log.error("[{}], {}, 获取用户小程序授权code信息异常, appId:{}, secret:{}, code:{}, anonymousCode:{}, err:{}", TAG, uuid, appId, secret, code, anonymousCode, e.getMessage(), e);
            return ResponseDTO.fail("获取用户小程序授权code信息异常");
        }
        log.info("[{}], {}, 获取用户小程序授权code信息jsonResult: {}", TAG, uuid, jsonResult);
        ByteBeatMinProgramSessionInfo byteBeatMinProgramSessionInfo = JSON.parseObject(jsonResult, ByteBeatMinProgramSessionInfo.class);
        if (!Objects.equals(0, byteBeatMinProgramSessionInfo.getError())) {
            log.error("[{}], {}, 获取用户小程序授权code信息失败, appId:{}, secret:{}, code:{}, anonymousCode:{}, jsonResult:{}", TAG, uuid, appId, secret, code, anonymousCode, jsonResult);
            return ResponseDTO.fail("获取用户小程序授权code信息失败");
        }
        return ResponseDTO.success(byteBeatMinProgramSessionInfo);
    }

    /**
     * 设置UserInfo
     * @param openId
     * @param beatMinProgramSessionInfo
     * @param byteBeatUserInfo
     * @param gender
     * @return
     */
    private UserInfo setUserInfo(String openId,ByteBeatMinProgramSessionInfo beatMinProgramSessionInfo,ByteBeatUserInfo byteBeatUserInfo,Integer gender){
        return UserInfo.builder()
                .userId(null)
                .openId(openId)
                .unionId(beatMinProgramSessionInfo.getUnionId())
                .type(GlobalConsts.NO)
                .realname(StringUtil.isBlank(byteBeatUserInfo.getNickName()) ? "头条用户" : byteBeatUserInfo.getNickName())
                .username(null)
                .nickName(byteBeatUserInfo.getNickName())
                .avatarSrc(byteBeatUserInfo.getAvatarUrl())
                .age(null)
                .gender(gender)
                .country(byteBeatUserInfo.getCountry())
                .province(byteBeatUserInfo.getProvince())
                .city(byteBeatUserInfo.getCity())
                .build();
    }


    /**
     * 设置PlatInfo
     * @param dio
     * @param app
     * @param channelId
     * @return
     */
    private PlatInfo setPlatInfo(UserAuthLoginDIO dio,AppDRO app,Integer channelId){
        return PlatInfo.builder()
                .shopId(dio.getShopId())
                .plat(app.getPlat())
                .channelId(channelId)
                .channelName(getNameByChannelId(channelId))
                .entrance(dio.getEntrance())
                .build();
    }


    /**
     * 设置ThirdAppInfo
     * @param app
     * @return
     */
   private ThirdAppInfo setThirdAppInfo(AppDRO app){
       return ThirdAppInfo.builder()
               .appId(app.getThirdAppId())
               .appName(app.getName())
               .appSecret(app.getThirdAppSecret())
               .build();
   }


    /**
     * 设置UserOtherInfo
     * @param beatMinProgramSessionInfo
     * @return
     */
   private UserOtherInfo setUserOtherInfo(ByteBeatMinProgramSessionInfo beatMinProgramSessionInfo){
       return UserOtherInfo.builder()
               .language(null)
               .sessionKey(beatMinProgramSessionInfo.getSessionKey())
               .build();
   }


    /**
     * 设置UserAuthLoginInfo
     * @param info
     * @param userOtherInfo
     * @param platInfo
     * @param thirdAppInfo
     * @param userPhoneInfo
     * @return
     */
   private UserAuthLoginInfo setUserAuthLoginInfo(UserInfo info,UserOtherInfo userOtherInfo,PlatInfo platInfo,ThirdAppInfo thirdAppInfo,UserPhoneInfo userPhoneInfo){
       return UserAuthLoginInfo.builder()
               .userInfo(info)
               .userOtherInfo(userOtherInfo)
               .platInfo(platInfo)
               .thirdAppInfo(thirdAppInfo)
               .userPhoneInfo(userPhoneInfo)
               .build();
   }
}
